Automatikus körzetesítés
Egy korábbi cikkben már összeszedtem az Oracle beépített Spatial függényeiből néhány fontosabbat. Ezúttal rendszerbe tesszük az egészet, és egy teljes folyamatba illesztjük be ezeket a függvényeket. A cél az, hogy automatikusan hozzunk létre körzeteket az ország területén.
Tételezzük fel, hogy egy magyarországi külföldi nagyvállalat telephelyeit (pl. kutyamosó boltokat) kell besorolnunk 1-1 körzetbe, méghozzá úgy, hogy minden körzetbe hozzávetőlegesen 120 kutyamosó tartozzon, minden településen belül hozzunk létre adott számú körzetet (azaz a körzetszám attól függ, hogy az adott településen belül hány darab kutyamosó található), és a körzet elemei - ahogy egy körzettől elvárható - egymás szomszédai legyenek, ne nagyon lógjanak át egymás területére.
A magoldáshoz segítségül hívjuk az Oracle Spatial függvényeit, illetve kezdésként szükségünk van olyan alapadatokra, amelyek a kutyamosók adatain túl (ID, cím, név, üzemeltető neve, stb...) X és Y koordinátákat is és EOV geometriát tartalmaz SDO_GEOMETRY típusú adatmezőben. A megjelenítéshez ingyenesen letölthető QuantumGIS alkalmazást használhatunk, vagy akár webes szolgáltatásként is megjeleníthetjük majd (pl. Geoserver-t használva).
A folyamat egészéről készítettem is egy folyamatábrát, hogy a saját megvalósításomban hogyan is mentem lépésről lépésre a megoldásig. Az első lépésekben meg kell vizsgálni, hogy az alapadatok rendelkezésre állnak, az Oracle Spatial kiterjesztése telepítésre került az adatbázisban, illetve a geometriát tartalmazó táblák is megkapták a szükséges spatial indexeket. Mivel országos szintű kutyamosó hálózatról beszélünk, minden megyére külön futtatjuk a folyamatot, és minden megyén belül lépünk végig az összes releváns településen.
A harmadik lépésben jutunk el oda, hogy elkezdjük felépíteni az egyes körzeteket minden településre. Ennek keretében egyszerű sorba rendezéssel ki tudjuk jelölni a településen található legnyugatabbi pontot, amely a kiindulópontunk lesz a további folyamatban. Ezzel együtt megnézzük, hogy az adott településen hány kutyamosó található, azzal könnyen elmenthető 1-1 változóban a leendő körzetek száma, valamint azok elemszáma. Ezt követően a kiindulóponttól indulva minden körzetre vonatkozóan LOOP-ot indítunk.
Ezzel eljutottunk a negyedik lépésig, ahol már az SDO_NN függvényt bőszen használni fogjuk. A kódunk így néz ki (részlet):
SELECT t2.MVA02_SEPTEL, t2.EOV_ORACLE, t1.M003 name1, t2.M003 name2, sdo_geom.sdo_distance (t1.EOV_ORACLE, t2.EOV_ORACLE, 2) distanceAhol a v_table jelenti az input adattáblánkat, benne a geometriát tartalmazó mezővel (EOV_ORACLE), a v_point mező tartalmazza az adott körzet kiindulópontját (amelyet minden új körzetnél kiszámolunk úgy, hogy az előző körzet utolsó pontjához legközelebbi pontot vesszük), a v_m009t pedig az adott település kódja. Fontos még a cnum értéke is, amely a körzetek elemszámát tartalmazza (lásd fentebb kiszámoltuk). Az Oracle specifikációjával szemben azonban nem teljesen úgy működik a történet, ahogy az ott le van írva. Ahogy látható, az SDO_NN(t2.EOV_ORACLE, t1.EOV_ORACLE, ''sdo_batch_size=0'') = ''TRUE'' és a rownum <= '|| cnum ||' azok a kódok, amelynél az SDO_NN függvényt használjuk, majd az eredményt leszűkítjük a szükséges elemszámra. Az Oracle specifikációjával szemben azonban vannak olyan esetek, amikor egy füst alatt nem adja vissza a szükséges elemszámot, pedig bőven lenne még miből. Emiatt van szükség WHILE LOOP használatára, ahol megvizsgáljuk a végtáblába már beilesztett elemszámot. Amennyiben a cnum értékét még nem érte el, akkor újra futtatjuk a folyamatot, ezúttal kezdőpontnak választva az utolsónak bevitt ponthoz legközelebbi pontot.
FROM TY.'|| v_table ||' t1, TY.'|| v_table ||' t2
WHERE SDO_NN(t2.EOV_ORACLE, t1.EOV_ORACLE, ''sdo_batch_size=0'') = ''TRUE''
and t1.M003 = '''|| v_point ||''' and t1.M003 != t2.M003 and t2.M009T = '''|| v_m009t(m) ||''' and rownum <= '|| cnum ||'
Amint eljutottunk oda, hogy elértük a szükséges elemszámot, megyünk a következő körzethez, és újra lejátszuk az eddigi folyamatot. Ha a település összes eleme elfogyott, megyünk a következő településre, és visszatérünk a folyamat előző pontjaihoz. Nagy vonalakban ez a folyamat, amennyiben valakit érdekel maga a forráskód, szívesen megosztom, csak írjatok nekem. Az alábbi képen egy mintát láthattok az elkészült eredményről, ahol a színek 1-1 körzetet jelentenek.
Ahogy fentebb írtam, az elkészült adattábla betehető webes megjelenítőbe (pl. Geoserver) vagy desktop alkalmazásba (pl. QuantumGIS), amelyekben utólagos manuális módosításokat is elvégezhetünk, de ez már egy másik folyamatot jelent.